package com.siping.并发.练习题;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author YangXu
 * @date 2021/9/11
 * @description:
 */
public class CompletableFutureTest {
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main start...");
        // runAsync
        /*CompletableFuture.runAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }, executor);*/

        /**
         * 方法完成后的感知
         */
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).whenComplete((res, exception) -> {
            // whenComplete是执行当前任务的线程继续执行whenComplete的任务，whenCompleteAsync则是会开启一个新的线程执行
            // 虽然能得到异常信息，但没法返回值。使用handle方法可以带有返回值
            System.out.println("异步任务执行成功...结果是：" + res );
        }).exceptionally(t->{
            // 可以指定一个默认返回值（比如发生异常可以返回一个默认值）
            return 10;
        });*/

        /**
         * 返回结果的处理
         */
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).handle((res, exception) -> {
            // whenComplete是执行当前任务的线程继续执行whenComplete的任务，whenCompleteAsync则是会开启一个新的线程执行
            // 虽然能得到异常信息，但没法返回值。使用handle方法可以带有返回值
            System.out.println("异步任务执行成功...结果是：" + res );

            return 10;
        });*/

        /**
         * 线程串行化
         * 1.thenApply方法：当一个线程依赖另外一个线程时，获取上一个任务的返回值并返回当前任务的返回值
         * 2.thenAccept方法：接收任务处理结果，并消费处理，无返回结果
         * 3.thenRun方法：只要上面的任务执行完成，就开始执行thenRun，只是处理完任务后，执行thenRun的后续操作
         * 带有Async默认是异步执行的，同之前
         */
        /*CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).whenComplete((u,e)->{}).thenRun(()->{
            System.out.println("线程的串行化");
        });*/

        /**
         * 两个任务组合，都要完成
         * 1、thenCombine：组合两个future，获取两个future的返回结果，并返回当前任务的返回值
         * 2、thenAcceptBoth：组合两个future，获取两个future的返回结果，没有返回值
         * 3、runAfterBoth：组合两个future，不需要获取future的返回结果，只需两个任务处理完成后执行任务
         */
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程：" + Thread.currentThread().getName());
            int i = 10 / 4;
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1线程结束..." );
            return i;
        }, executor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程：" + Thread.currentThread().getName());
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2线程结束..." );
            return "Hello";
        }, executor);

        future01.runAfterEitherAsync(future02, ()->{
            // 任务3在任务1和2执行完毕后执行
            System.out.println("任务3开始执行...");
        },executor);

        /**
         * 两个任务组合，两任务只要其中一个完成就可以
         * applyToEither：两任务有一个执行完成，获取它的返回值，处理任务并有新的返回值
         * acceptEither：两任务有一个执行完成，获取它的返回值，处理任务但没有新的返回值
         * runAfterEither：两任务有一个执行完成，不需要获取它的返回值，处理任务并有新的返回值
         */

        /**
         * 多任务组合
         * allOf: 所有任务完成
         * anyOf: 任何一个任务完成
         */
        CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02);
        allOf.get(); // 等待所有执行完成
        future01.get(); // 获取返回值
        future02.get();

//        Integer i = future.get();
        // 完成时回调
        System.out.println("main end...");
    }
}
